#include"Date.h"

bool Date::isLegal() {
	if (_year > 0) {
		if (_month > 0 && _month < 13) {
			if (_day > 0 && _day <= GetMonDays()) {
				return true;
			}
		}
	}
	return false;
}

bool Date::isGapYear() {
	if ((_year % 4 == 0 && _year % 100 != 0) || (_year % 400 == 0)) {
		return true;
	}
	else {
		return false;
	}
}

const int Date::GetMonDays() {
	static int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
	if (_month == 2 && isGapYear()) {
		return days[_month - 1] + 1;
	}
	return days[_month - 1];
}

bool Date::operator>(const Date& date) const {
	if (_year > date._year) {
		return true;
	}
	else if (_year == date._year && _month > date._month) {
		return true;
	}
	else if (_year == date._year && _month == date._month &&
		_day > date._day) {
		return true;
	}
	else {
		return false;
	}
}

bool Date::operator<(const Date& date) const {
	if (_year < date._year) {
		return true;
	}
	else if (_year == date._year && _month < date._month) {
		return true;
	}
	else if (_year == date._year && _month == date._month &&
		_day < date._day) {
		return true;
	}
	else {
		return false;
	}
}

bool Date::operator==(const Date& date) const {
	return this->_year == date._year && this->_month
		== date._month && this->_day == date._day;
}

bool Date::operator>=(const Date& date) const {
	return *this > date || *this == date;
}

bool Date::operator<=(const Date& date) const {
	return *this < date || *this == date;
}

Date& Date::operator+=(const int days) {
	_day += days;
	int cur_day = GetMonDays();
	while (cur_day < _day) {
		_day -= cur_day;
		++_month;
		if (_month > 12) {
			_month = 1;
			++_year;
		}
		cur_day = GetMonDays();
	}
	return *this;
}

Date& Date::operator++() {
	*this += 1;
	return *this;
}

const Date Date::operator++(int i) {
	Date cur = *this;
	*this += 1;
	return cur;
}

const Date Date::operator+(const int days) {
	Date cur = *this;
	cur += days;
	return cur;
}

Date& Date::operator-=(const int days) {
	_day -= days;
	int cur_day = GetMonDays();
	while (_day < 1) {
		--_month;
		if (_month < 1) {
			--_year;
			_month = 12;
		}
		cur_day = GetMonDays();
		_day += cur_day;
	}
	return *this;
}

Date& Date::operator--() {
	*this -= 1;
	return *this;
}

const Date Date::operator--(int i) {
	Date cur = *this;
	*this -= 1;
	return cur;
}

const Date Date::operator-(const int days) {
	Date cur = *this;
	cur -= days;
	return cur;
}

const int BetweenDays(const Date& d1, const Date& d2) {
	Date max = d1, min = d2;
	if (max < min) {
		max = d2, min = d1;
	}
	int days = 0;
	if (max._year > min._year) {
		Date cur_max(max._year, 1, 1);
		Date cur_min(min._year, 12, 31);
		while (cur_max._month < max._month) {
			days += cur_max.GetMonDays();
			++cur_max._month;
		}
		days += max._day;
		while (cur_min._month > min._month) {
			days += cur_min.GetMonDays();
			--cur_min._month;
		}
		days += (cur_min.GetMonDays() - min._day);
		++cur_min._year;
		while (cur_min._year < max._year) {
			days += 365;
			if (cur_min.isGapYear()) {
				days += 1;
			}
			++cur_min._year;
		}
	}
	else {
		while (min < max) {
			++days;
			++min;
		}
	}
	return days;
}

ostream& operator<<(ostream& output, const Date& date) {
	output << date._year << "/" << date._month << "/" << date._day;
	return output;
}

istream& operator>>(istream& input, Date& date) {
	input >> date._year >> date._month >> date._day;
	while (!date.isLegal()) {
		cout << "illegal date, input again!" << endl;
		input >> date._year >> date._month >> date._day;
	}
	return input;
}